package com.cysyz.module.log.business.aspect;


import com.cysyz.module.log.business.domain.EntityInfo;
import com.cysyz.module.log.business.domain.SysBusinessLog;
import com.cysyz.module.log.business.domain.SysBusinessLogTargetEntity;
import com.cysyz.module.support.service.BaseService;
import com.cysyz.mylib.myfilter.MyFilter;
import com.cysyz.mylib.myfilter.impl.SimpleMyFilter;
import com.cysyz.mylib.utils.MyBeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;

@Aspect
public class BusinessLogOperateEntityPersistAspect extends BaseService {
    MyFilter propertyNameFilter;

    public BusinessLogOperateEntityPersistAspect() {
        Collection excludes =new ArrayList();
        excludes.add("version");
        Collection includex = new ArrayList();
        propertyNameFilter = new SimpleMyFilter(includex, excludes);
    }


    private void pointCutMethod() {
    }
  
    //声明环绕通知  
/*    @Around("pointCutMethod()")*/
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        if (ServletActionContext.getContext() != null) {
            Object[] args = pjp.getArgs();
            Signature signature = pjp.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();

            if (args != null && args.length >= 1) {

                BaseEntity methodArgEntity = (BaseEntity) args[0];

                saveBusinessLogTargetEntityInfo(method, methodArgEntity);
            }
        }
        Object o = pjp.proceed();

        return o;
    }

    private void saveBusinessLogTargetEntityInfo(Method method, BaseEntity methodArgEntity) throws IllegalAccessException, InvocationTargetException {
        if (methodArgEntity.getClass() != SysBusinessLogTargetEntity.class && methodArgEntity.getClass() != SysBusinessLog.class) {
            List<EntityInfo.ColumnInfo> columnInfosBeforechanged = new ArrayList<>();

            List<EntityInfo.ColumnInfo> columnInfosAfterchanged = new ArrayList<>();

            if (method.getName().equals("persist")) {

                columnInfosAfterchanged = getColumnInfos(methodArgEntity);

            } else if (method.getName().equals("merge")) {

                BaseEntity changedBeforeEntity = this.get(methodArgEntity.getClass(), methodArgEntity.getId());

                columnInfosBeforechanged = getColumnInfos(changedBeforeEntity);

                columnInfosAfterchanged = getColumnInfos(methodArgEntity);


            } else if(method.getName().equals("remove")) {
                columnInfosBeforechanged = getColumnInfos(methodArgEntity);
            }

            EntityInfo entityInfo = new EntityInfo();
            entityInfo.setColumnInfosBeforeChanged(columnInfosBeforechanged);
            entityInfo.setColumnInfosAfterChanged(columnInfosAfterchanged);
            JSONObject jsonObject = JSONObject.fromObject(entityInfo);

            SysBusinessLogTargetEntity businessLogTargetEntity = new SysBusinessLogTargetEntity();
            businessLogTargetEntity.setEntityName(methodArgEntity.getClass().getSimpleName());
            businessLogTargetEntity.setEntityChangedInfoJson(jsonObject.toString());
            SysBusinessLog businessLog = ServletActionContext.getBusinessLog();
            businessLogTargetEntity.setBusinessLog(businessLog);
            this.save(businessLogTargetEntity);
        }
    }

    private List<EntityInfo.ColumnInfo> getColumnInfos(BaseEntity arg) throws IllegalAccessException, InvocationTargetException {
        List<EntityInfo.ColumnInfo> columnInfos = new ArrayList<>();

        ClassMetadata classMetaData = this.getClassMetaData(arg.getClass());
        String[] propertyNames = classMetaData.getPropertyNames();

        for (String propertyName : propertyNames) {
            PropertyDescriptor propertyDescriptor = MyBeanUtils.getPropertyDescriptor(arg.getClass(), propertyName);
            if (propertyNameFilter.filter(propertyName)
                    && propertyDescriptor.getPropertyType() != List.class
                    && propertyDescriptor.getPropertyType() != Set.class) {

                Object propertyValue = propertyDescriptor.getReadMethod().invoke(arg);
                if (BaseEntity.class.isAssignableFrom(propertyDescriptor.getPropertyType())) {
                    propertyValue = ((BaseEntity)propertyValue).getId();
                }
                columnInfos.add(new EntityInfo.ColumnInfo(propertyDescriptor.getShortDescription(), propertyValue == null ? "" : propertyValue.toString()));
            }

        }
        return columnInfos;
    }
} 